/*
    XHoldingPattern
    Copyright (C) 2009 Mike Gehl

    X-Plane Plugin SDK
    Copyright (C) Sandy Barbour and Ben Supnik

    Great Circle Navigation Calculations
    source: http://williams.best.vwh.net/avform.htm
    vasFMC Copyright (C) 2005-2006 Alexander Wemmer

    This file is part of XHoldingPattern.

    XHoldingPattern is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    XHoldingPattern is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with XHoldingPattern.  If not, see <http://www.gnu.org/licenses/>.
    ---------------------------------------------------------------------------
    xHoldPattern.c
    Copyright (C) Mike Gehl 2009 <mjgehl@gmail.com>

    X-Plane plugin entry point. Init the plugin, create menus, callback
    functions, and ...
*/

#include <stdio.h>
#include <string.h>


#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include "XPLMNavigation.h"
#include "XPLMUtilities.h"
#include "about.h"
#include "pattern.h"
#include "xHoldPattern.h"

int gHoldPatStatus;
PATTERN_DATA gPattern_data;
XPLMWindowID	gWindow = NULL;

PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc)
{
	strcpy(outName, "XHoldingPattern");
	strcpy(outSig, "xplane.aav.xholdpattern");
	strcpy(outDesc, "A plugin that automates a holding pattern.");

	gWindow = XPLMCreateWindow(
					10, 680, 500, 150,			/* Area of the window. L,T,R,B*/
					1,							/* Start visible. */
					holdpat_window_callback,	/* Callbacks */
					NULL,
					NULL,
					NULL);						/* Refcon - not used. */


	/* Data refs to record. */
	gZuluTime      = XPLMFindDataRef("sim/time/zulu_time_sec");
	gPlaneTAS      = XPLMFindDataRef("sim/flightmodel/position/true_airspeed");
	gPlaneAlt      = XPLMFindDataRef("sim/flightmodel/position/elevation");
	gPlanePitch    = XPLMFindDataRef("sim/flightmodel/position/theta");
	gPlaneRoll     = XPLMFindDataRef("sim/flightmodel/position/phi");
	gPlaneHeading  = XPLMFindDataRef("sim/flightmodel/position/psi");
	gPlaneIAS      = XPLMFindDataRef("sim/flightmodel/position/indicated_airspeed");
	gWindSpeed     = XPLMFindDataRef("sim/weather/wind_speed_kt");
	gWindDirection = XPLMFindDataRef("sim/weather/wind_direction_degt");

	/* Register the callback for once a second.  */
	XPLMRegisterFlightLoopCallback(
			holdpat_loop_callback,	/* Callback */
			HOLDPAT_INTERVAL,		/* Interval */
			NULL);					/* refcon not used. */


	XPLMMenuID	myMenu;
    int			mySubMenuItem;

	/* First we put a new menu item into the plugin menu.
	 * This menu item will contain a submenu for us. */
	mySubMenuItem = XPLMAppendMenuItem(
						XPLMFindPluginsMenu(),	/* Put in plugins menu */
						"XHoldPattern",	        /* Item Title */
						0,						/* Item Ref */
						1);						/* Force English */

	/* Now create a submenu attached to our menu item. */
	myMenu = XPLMCreateMenu(
						"holdpat",
						XPLMFindPluginsMenu(),
						mySubMenuItem, 			/* Menu Item to attach to. */
						holdpat_menu_callback,	/* The handler */
						0);						/* Handler Ref */

	/* Append menu items to submenu. */
	XPLMAppendMenuItem( myMenu,
						"Holding Pattern - ON",
						(void *) HOLDPAT_MENU_ON,
						1);
	XPLMAppendMenuItem( myMenu,
						"Holding Pattern - OFF",
						(void *) HOLDPAT_MENU_OFF,
						1);
    XPLMAppendMenuSeparator(myMenu);

    XPLMAppendMenuItem( myMenu,
						"About...",
						(void *) HOLDPAT_MENU_ABOUT,
						1);

    gHoldPatStatus = HOLDPAT_OFF;
    return 1;
}

PLUGIN_API void	XPluginStop(void)
{
	XPLMUnregisterFlightLoopCallback(holdpat_loop_callback, NULL);
	holdpat_stop( );
}

PLUGIN_API int XPluginEnable(void)
{
	return 1;
}

PLUGIN_API void XPluginDisable(void)
{
}

PLUGIN_API void XPluginReceiveMessage(
					XPLMPluginID	inFromWho,
					long			inMessage,
					void *			inParam)
{
}


/**********************************************************************/
void holdpat_menu_callback( void *inMenuRef, void *inItemRef)
{
    if ((long) inItemRef == HOLDPAT_MENU_ON)
        holdpat_start( );

    if ((long) inItemRef == HOLDPAT_MENU_OFF)
        holdpat_stop( );

    if ((long) inItemRef == HOLDPAT_MENU_ABOUT)
        holdpat_about_dialog( );
}

float holdpat_loop_callback( float inElapsedSinceLastCall,
                            float inElapsedTimeSinceLastFlightLoop,
                            int inCounter,
                            void *inRefcon)
{
    if (gHoldPatStatus == HOLDPAT_ON)
    {
        update_position(XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/latitude")),
                        XPLMGetDataf(XPLMFindDataRef("sim/flightmodel/position/longitude")),
                        &gPattern_data);

        if (gPattern_data.distance > 5000) // distance from fix > 3 miles
            gPattern_data.leg = INTERCEPT; // force pattern intercept

        switch(gPattern_data.leg)
        {
            case INTERCEPT:
                pattern_intercept(&gPattern_data);
                XPLMSetDataf(XPLMFindDataRef("sim/cockpit/autopilot/heading"),
                        gPattern_data.heading);
                break;
            case INBOUND_LEG:
                break;
            case OUTBOUND_TURN:
                break;
            case OUTBOUND_LEG:
                break;
            case INBOUND_TURN:
                break;
        }
    }

	/*  Return Time interval that we want to be called again. */
	return HOLDPAT_INTERVAL;
}

void holdpat_window_callback( XPLMWindowID inWindowID, void *inRefcon)
{
    int		left, top, right, bottom;
	float	color[] = { 0.5742, .832, .7109 }; 	/* Green */

	XPLMGetWindowGeometry(inWindowID, &left, &top, &right, &bottom);

	/* Finally we draw the text into the window, also using XPLMGraphics
	 * routines.  The NULL indicates no word wrapping. */
    char buf[256];
    strcpy(buf, "XHoldPattern DEBUG");
	XPLMDrawString(color, left, top, buf, NULL, xplmFont_Basic);
	strcpy(buf, "------------------");
	XPLMDrawString(color, left, top-10, buf, NULL, xplmFont_Basic);
	sprintf(buf, "planelat  = %f", rad2deg(gPattern_data.plane_lat));
	XPLMDrawString(color, left, top-20, buf, NULL, xplmFont_Basic);
	sprintf(buf, "planelon  = %f", rad2deg(gPattern_data.plane_lon));
	XPLMDrawString(color, left, top-30, buf, NULL, xplmFont_Basic);
	sprintf(buf, "navaidlat = %f", rad2deg(gPattern_data.navaid_lat));
	XPLMDrawString(color, left, top-40, buf, NULL, xplmFont_Basic);
	sprintf(buf, "navaidlon = %f", rad2deg(gPattern_data.navaid_lon));
	XPLMDrawString(color, left, top-50, buf, NULL, xplmFont_Basic);

	sprintf(buf, "distance  = %f", meters2miles(gPattern_data.distance));
	XPLMDrawString(color, left, top-70, buf, NULL, xplmFont_Basic);
	sprintf(buf, "traffic   = %d", gPattern_data.direction);
	XPLMDrawString(color, left, top-80, buf, NULL, xplmFont_Basic);
	sprintf(buf, "leg       = %d", gPattern_data.leg);
	XPLMDrawString(color, left, top-90, buf, NULL, xplmFont_Basic);
	sprintf(buf, "heading   = %f", gPattern_data.heading);
	XPLMDrawString(color, left, top-100, buf, NULL, xplmFont_Basic);
}


void holdpat_stop( )
{
    gHoldPatStatus = HOLDPAT_OFF;
}

void holdpat_start( )
{
    if (gHoldPatStatus == HOLDPAT_OFF)
    {
        char  nav_name[6] = "BENKY";
        char  nav_ID[6] = "BENKY";
        float nav_lat;
        float nav_lon;
        float nav_heading;
        int   nav_freq;
        XPLMNavType nav_type = xplm_Nav_NDB + xplm_Nav_VOR + xplm_Nav_Fix;

        XPLMNavRef nav_ref = XPLMFindNavAid(nav_name,
                                    NULL, NULL, NULL, NULL,
                                    nav_type);

        XPLMGetNavAidInfo(nav_ref,
                       NULL, &nav_lat, &nav_lon,
                       NULL, NULL, NULL, NULL, NULL, NULL);

        gPattern_data.radius = XPLMGetDataf(XPLMFindDataRef("sim/physics/earth_radius_m"));
        gPattern_data.navaid_lat = nav_lat;
        gPattern_data.navaid_lon = nav_lon;
        gPattern_data.course = 67.0;  // Inbound leg
        gPattern_data.direction = PATTERN_RIGHT;
        gPattern_data.leg = INTERCEPT;
    }
    gHoldPatStatus = HOLDPAT_ON;

}


